
#pragma once

using namespace System::Collections::Generic;
using namespace NUnit::Framework;

#include <ttg/services.h>

//Test classes
class TimeEventCounter
{
	public:
		int count;
		inline TimeEventCounter()
		{ count = 0; }
		static void onTick(TimeEventCounter *object, double time)
		{ object->count += 1; }
};

namespace RuntimeLowTests
{
	namespace services
	{
		[TestFixture]
		public ref class TimerTests
		{
			public:
				void CheckResolution(double duration, double step)
				{
					TimeEventCounter counter;
					ttg::services::ServiceBase::getRef()->start();
					double t_start = System::Environment::TickCount / 1000.0;
					ttg::services::Timer::getRef()
						->setNotifier(ttg::structures::make_delegate(&counter, TimeEventCounter::onTick),
									  step,
									  true);
					System::Threading::Thread::CurrentThread->Sleep((DWORD)(duration * 1000));
					ttg::services::ServiceBase::getRef()->stop();
					double t_end = System::Environment::TickCount / 1000.0;
					Assert::AreEqual(true, counter.count * step <= t_end - t_start + step  + 0.001 / step &&
										   counter.count * step >= duration - step - 0.001 / step,
									 System::String::Format("Notifier is too inaccurate: {0} vs {1}",
															counter.count * step, t_end - t_start));
				}

				[Test]
				void TimeEvent_128ms()
				{ CheckResolution(1.024, 0.128); }

				[Test]
				void TimeEvent_64ms()
				{ CheckResolution(1.024, 0.064); }

				[Test]
				void TimeEvent_32ms()
				{ CheckResolution(1.024, 0.032); }

				[Test]
				void TimeEvent_16ms()
				{ CheckResolution(1.024, 0.016); }

				[Test]
				void TimeEvent_8ms()
				{ CheckResolution(1.024, 0.008); }
		};
	}
}
